<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .box1{width:1000px;height:100px;padding:10px 0;position: relative;border: solid 1px black;margin-bottom:50px;}
        .xbox1{width:100px;height:100px;background: red;position: absolute;left:0;top:10px}
        .box2{width:1000px;height:100px;padding:10px 0;position: relative;border: solid 1px black;}
        .xbox2{width:100px;height:100px;background: red;position: absolute;left:0;}
    </style>
</head>
<body>
    <div class="box1">
        hello
        <div class="xbox1"></div>
    </div>
</body>
<script>

    const obox1 = document.querySelector(".box1");
    const oxbox1 = document.querySelector(".xbox1");

    obox1.onclick = function(){
        move(oxbox1, {
            opacity: 10,left:400
        });
    }

    function move(ele, obj, callback){
        clearInterval(ele.time);
        ele.time = setInterval(()=>{
            let flag = true;
            for(let i in obj){
                // 透明属性需要单独处理
                let now = i==="opacity" ? getStyle(ele, i)*100 : parseInt(getStyle(ele, i));

                let speed = (obj[i] - now) / 10;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                
                // 透明属性需要单独处理
                ele.style[i] = i==="opacity" ? (now+speed)/100 : now+speed+"px";

                console.log(now)
                if(now !== obj[i]){
                    flag = false;
                }
            }
            if(flag){
                clearInterval(ele.time);
                // 执行的功能是不确定的，传参，传的是功能
                // 根据是否传入回调函数，决定执行或不执行
                // 利用逻辑短路简化if代码
                callback && callback();
            }
        }, 30);
    }

    // 获取非行内样式的兼容封装
    function getStyle(ele, attr){
        if(getComputedStyle){
            return getComputedStyle(ele)[attr];
        }else{
            return ele.currentStyle[attr];
        }
    }

    
</script>
</html>